import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class WindowFrame extends JFrame{
	private static final long serialVersionUID = 1L;
	private LexAnalysis lex;
	private JMenuBar menuBar;
    private JMenu menuFile;
    private JMenu menuProject;
    private JTextArea jTextArea;
    private JScrollPane jScrollPane;
    private JMenuItem itemOpen;
    private JMenuItem itemLex;
    
    private FileDialog open,save;
    private File file;  
    private JPanel tablePanel;
    private JScrollPane tokenJScrollPane;
    private JTable tokenTable;
    String[] tokenColumnNames = {"符号类型", "符号值"};
    private TableModel tokenTableModel = new DefaultTableModel(tokenColumnNames, 0);
    private JTextArea errorMessage;
    private JScrollPane errorPane;
    private List<Token> allToken;
    private String consoleMessage;
    private int readNum = 0;
    private List<String> output;
    private boolean success = false;
    
    public static void main(String[] args) {
		new WindowFrame();
	}
    
    public WindowFrame() {
    	init();
    }

    private void init() {
	    JFrame frame = new JFrame("编译原理词法分析");
	    frame.setBounds(300, 300, 700, 450);
	    frame.setDefaultCloseOperation(EXIT_ON_CLOSE);

	    menuBar = new JMenuBar();
	    menuFile = new JMenu("文件");
	    menuProject = new JMenu("词法分析");
	    
	    jTextArea = new JTextArea(10, 40);
	    jTextArea.setFont(new Font("Monospaced",1,20));
	    jTextArea.setLineWrap(true);
	    jScrollPane = new JScrollPane(jTextArea);
	    jScrollPane.setHorizontalScrollBarPolicy( JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
	    jScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 
	    jScrollPane.setViewportView(jTextArea);
	    itemOpen = new JMenuItem("打开");
	    itemLex = new JMenuItem("词法分析");

	    menuBar.add(menuFile);
	    menuBar.add(menuProject);
	    menuFile.add(itemOpen);
	    menuProject.add(itemLex);
	    
	    tokenTable = new JTable(tokenTableModel);
	    tokenTable.setPreferredScrollableViewportSize(new Dimension(300, 100));
        tokenTable.setFillsViewportHeight(true);
        tokenJScrollPane = new JScrollPane(tokenTable);

        tablePanel = new JPanel();
        tablePanel.setLayout( new GridLayout (0, 1));
        tablePanel.add(tokenJScrollPane);

		errorMessage = new JTextArea();
		errorPane = new JScrollPane(errorMessage);
		errorPane.setPreferredSize(new Dimension(700, 100));

	    frame.add(menuBar, BorderLayout.NORTH);
	    frame.add(jScrollPane, BorderLayout.CENTER);
	    frame.add(tablePanel, BorderLayout.EAST);
	    frame.add(errorPane, BorderLayout.SOUTH);
            
	    open = new FileDialog(frame,"打开文件",FileDialog.LOAD);
	    save = new FileDialog(frame,"保存文件",FileDialog.SAVE); 

	    Event();
	    frame.setVisible(true);
    }

    private void Event() {
	  
	    
		itemOpen.addActionListener(new ActionListener() {
		    public void actionPerformed(ActionEvent e) {  
		        open.setVisible(true);  

		        String dirPath = open.getDirectory();  
	            String fileName = open.getFile();  
	            if (dirPath == null || fileName == null) {
	            	return;
	            }   
	            file = new File(dirPath, fileName);   

		     	jTextArea.setText("");

	            try { 
	                BufferedReader br = new BufferedReader(new FileReader(file));  
	                String line = null;  
	                while ((line = br.readLine()) != null) {  
	                    jTextArea.append(line + "\r\n");  
	                }  
	            }  
	            catch (IOException ex) {  
	                throw new RuntimeException("读文件失败");  
	            }  
	        }  
	    });  

	    itemLex.addActionListener(new ActionListener() {
	    	public void actionPerformed(ActionEvent e) {
	    		compile();
	    	}
	    });
	}

	private void compile() {
		if (file == null) {
			JOptionPane.showMessageDialog(null, "保存文件");
			newFile();
		}
		saveFile();
		lex = new LexAnalysis(file);//CiFa
		allToken = lex.getAllToken();
		clean();
		displayAllToken();
		consoleMessage += "Lex succeed!\n";
		errorMessage.setText(consoleMessage);
	}

	private void clean() {
		flushTable(tokenTable);
		errorMessage.setText("");
		consoleMessage = "";
		success = false;
	}

	private void displayAllToken() {
		DefaultTableModel model = (DefaultTableModel)tokenTable.getModel();
		allToken = lex.getAllToken();
		for (int i = 0; i < allToken.size(); i++) {
			Token token = allToken.get(i);
			Object[] rowValues = {token.getSt(), token.getValue(), token.getLine()};
			model.addRow(rowValues);
		}
	}
	
	private void flushTable(JTable table) {
		((DefaultTableModel) table.getModel()).getDataVector().clear();  
		((DefaultTableModel) table.getModel()).fireTableDataChanged();
		table.updateUI();
	}

    private void newFile() {
    	if (file == null) {  
            save.setVisible(true);  
            String dirPath = save.getDirectory();  
            String fileName = save.getFile();  
            if(dirPath == null || fileName == null) {
                return;  
            }
            file = new File(dirPath, fileName);                
        }  
    }

    private void saveFile() {
        try {  
            BufferedWriter bw = new BufferedWriter(new FileWriter(file));  
            String text = jTextArea.getText();  
            bw.write(text);  
            bw.close();  
        } catch (IOException ex) {  
            throw new RuntimeException();  
        }  
    }
}
